﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Storage;
using Storage.EntityModels;
using System.Data.Linq;

namespace Stats
{
    /// <summary>
    /// This class contains the methods for reading the daily statististics table.
    /// </summary>
    public class ReadDailyStatsTableModule
    {

        /// <summary>
        /// Get the values for a year for a specific subject.
        /// </summary>
        /// <param name="subject">
        /// The subject identifies a type of statistical data. Each data refers to a single month of a year. Possible subjects are:<br/>
        /// "totalPassengers": the number of passengers of overall trips
        /// "savedPollution": the estimated amount of pollution saved by the sytem usage measured in hundreds of kg of CO2
        /// "savedMoney": the estimated amount of money saved measured in EUR.
        /// "savedFuel": the estimated amount of fuel saved measured in liters.
        /// "doneKilometers": the total amount of kilometers of all the trips.
        /// "dailyTripProposed": number of trips proposed by users.
        /// "dailyTripCompleted": number of trips completed.
        /// "missedAppointmentByDrivers": number of passengers that missed a trip because of the driver.
        /// "missedAppointmentByPassengers": number of appointments missed by passengers.
        /// "carriedPassengers": number of passengers carried along the trip.
        /// "registeredUsers": number of registered users.
        /// "averageTripKm": total number of trips kilometers divided by the number of trips.
        /// "maxPassengers": maximum passengers for a single trips.
        /// </param>
        /// <param name="year">the year the data are requested for</param>
        /// <returns>An array of 12 integers. Each integer is the data for a month.</returns>
        public static int[] getYearStats(string subject, int year)
        {
            TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

            int[] res = new int[12];
            
            //TODO: non esiste la Sum() per gli IQueryable<short> ...! fai mettere a storage che tutti i campi sono interi non nulli.
            switch (subject)
                {
                    case ("totalPassengers"):
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.TotalPassengers)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case ("savedPollution"):
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.PollutionSaved)
                               );
                            if (result.Count() != 0) res[i] = (int) result.First();
                        }
                        break;
                    case ("savedMoney"):
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.MoneySaved)
                               );
                            if (result.Count() != 0) res[i] = (int)result.First();
                        }
                        break;
                    case "savedFuel":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.FuelSaved)
                               );
                            if (result.Count() != 0) res[i] =(int) result.First();
                        }
                        break;
                    case "doneKilometers":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.TotalKilometers)
                               );
                            if (result.Count() != 0) res[i] =(int) result.First();
                        }
                        break;
                    case "dailyTripProposed":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.TotalDailyTripProposal)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case "dailyTripCompleted":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.DailyCompletedTrips)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case "missedAppointmentByDrivers":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.MissedAppointmentsByDrivers)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case "missedAppointmentByPassengers":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.MissedAppointmentsByPassengers)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case "carriedPassengers":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Sum(g => g.PassengerCarriedAlongTheWay)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case "registeredUsers":
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Max(g => g.RegisteredUsersCount)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                    case ("averageTripKm"):
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Average(g => g.AverageTripKm)
                               );
                            if (result.Count() != 0) res[i] = (int)result.First();
                        }
                        break;
                    case ("maxPassengers"):
                        for (int i = 0; i < res.Length; i++)
                        {
                            var result =
                               (from dailyEntry in db.DailyStatistics
                                where dailyEntry.Date.Year == year && dailyEntry.Date.Month == i + 1
                                group dailyEntry by dailyEntry.Date.Month into monthGroup
                                select monthGroup.Max(g => g.MaximumPassengers)
                               );
                            if (result.Count() != 0) res[i] = result.First();
                        }
                        break;
                }
            
            return res;
        }

        /// <summary>
        /// Get the values for a month for a specific subject.
        /// </summary>
        /// <param name="subject">
        /// The subject identifies a type of statistical data. Each data refers to a single day of the month. Possible subjects are:<br/>
        /// "totalPassengers": the number of passengers of overall trips
        /// "savedPollution": the estimated amount of pollution saved by the sytem usage measured in hundreds of kg of CO2
        /// "savedMoney": the estimated amount of money saved measured in EUR.
        /// "savedFuel": the estimated amount of fuel saved measured in liters.
        /// "doneKilometers": the total amount of kilometers of all the trips.
        /// "dailyTripProposed": number of trips proposed by users.
        /// "dailyTripCompleted": number of trips completed.
        /// "missedAppointmentByDrivers": number of passengers that missed a trip because of the driver.
        /// "missedAppointmentByPassengers": number of appointments missed by passengers.
        /// "carriedPassengers": number of passengers carried along the trip.
        /// "registeredUsers": number of registered users.
        /// "averageTripKm": total number of trips kilometers divided by the number of trips.
        /// "maxPassengers": maximum passengers for a single trips.
        /// </param>
        /// <param name="year">the year the data are requested for</param>
        /// <param name="month">the month the data are requested for [1-12]</param>
        /// <returns>An array of N integers where N is the number of days in the month. Each integer is the data for a day. E.g, result[0] is the data for the first day of the month.</returns>
        public static int[] getMonthStats(string subject, int year, int month)
        {
            TripLoaDataContext db = Storage.StorageManager.Instance.Entities;

            int[] result = new int[DateTime.DaysInMonth(year, month)];
            
            switch (subject)
            {
                case ("totalPassengers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.TotalPassengers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("savedPollution"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.PollutionSaved });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int) dayData.data;

                        break;
                    }
                case ("savedMoney"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.MoneySaved });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int)dayData.data;

                        break;
                    }
                case ("savedFuel"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.FuelSaved });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int)dayData.data;

                        break;
                    }
                case ("doneKilometers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.TotalKilometers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int)dayData.data;

                        break;
                    }
                case ("dailyTripProposed"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.TotalDailyTripProposal });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("dailyTripCompleted"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.DailyCompletedTrips });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int)dayData.data;

                        break;
                    }
                case ("missedAppointmentByDrivers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.MissedAppointmentsByDrivers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("missedAppointmentByPassengers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.MissedAppointmentsByPassengers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("carriedPassengers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.PassengerCarriedAlongTheWay });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("registeredUsers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.RegisteredUsersCount });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                case ("averageTripKm"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.TotalKilometers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = (int)dayData.data;

                        break;
                    }
                case ("maxPassengers"):
                    {
                        var dataTable =
                         (from dailyEntry in db.DailyStatistics
                          where dailyEntry.Date.Month == month && dailyEntry.Date.Year == year
                          select new { day = dailyEntry.Date.Day, data = dailyEntry.MaximumPassengers });

                        foreach (var dayData in dataTable) result[dayData.day - 1] = dayData.data;

                        break;
                    }
                
            }
            return result;
        }



        
    }
}